package com.gopay.bis.manager.bank.expay;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.dao.bankorder.BankContractInfoDAO;
import com.gopay.bis.dao.corp.CustCorpInfoDao;
import com.gopay.bis.dao.payconfig.BisExpaySmsSendLogDAO;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.NuccSerialManager;
import com.gopay.common.cache.client.RedisClient;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOfAffiliationConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.cust.SMSType;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.dao.order.CpsGeneralReceiptOrderQueryDAO;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.NuccExpayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.NuccExpayHeaderMessage;
import com.gopay.common.domain.bank.nucc.expay.cert.NuccExpayCertBodyInstginf;
import com.gopay.common.domain.bank.nucc.expay.cert.NuccExpayCertBodySgninf;
import com.gopay.common.domain.bank.nucc.expay.cert.req.NuccExpayCertBodyReq;
import com.gopay.common.domain.bank.nucc.expay.cert.req.NuccExpayCertBodyTrxinf;
import com.gopay.common.domain.bank.nucc.expay.cert.res.NuccExpayCertRes;
import com.gopay.common.domain.bank.nucc.expay.pay.end.NuccExpaymentEndRes;
import com.gopay.common.domain.bank.nucc.expay.pay.req.*;
import com.gopay.common.domain.bank.nucc.expay.pay.res.NuccExpaymentRes;
import com.gopay.common.domain.bank.nucc.expay.query.req.NuccExpayQueryBodyOriTrxinf;
import com.gopay.common.domain.bank.nucc.expay.query.req.NuccExpayQueryBodyReq;
import com.gopay.common.domain.bank.nucc.expay.query.res.NuccExpayQueryRes;
import com.gopay.common.domain.bank.nucc.expay.refund.end.NuccExpayRefundEndRes;
import com.gopay.common.domain.bank.nucc.expay.refund.req.*;
import com.gopay.common.domain.bank.nucc.expay.refund.res.NuccExpayRefundRes;
import com.gopay.common.domain.bank.nucc.expay.rescind.req.NuccExpayRescindBodyInstginf;
import com.gopay.common.domain.bank.nucc.expay.rescind.req.NuccExpayRescindBodyReq;
import com.gopay.common.domain.bank.nucc.expay.rescind.req.NuccExpayRescindBodyRescindinf;
import com.gopay.common.domain.bank.nucc.expay.rescind.req.NuccExpayRescindBodySgninf;
import com.gopay.common.domain.bank.nucc.expay.rescind.res.NuccExpayRescindRes;
import com.gopay.common.domain.bank.nucc.expay.serial.req.NuccExpaySerialBodyReq;
import com.gopay.common.domain.bis.BisBankContractInfo;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cps.CpsGenReceiptOrder;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.log.BisExpaySmsSendLog;
import com.gopay.common.domain.pg.PgGenOrderTransDtl;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.dao.PgGeneralOrderTransDtlDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.remote.bank.businesses.ExPayService;
import com.gopay.remote.bank.businesses.SerialApplyService;
import com.ibm.icu.math.BigDecimal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** 
 * 网联快捷  manager类
 * @ClassName: NuccExPayManager 
 * @author w_jiqing 
 * @date 2017年7月13日 下午3:56:26  
 */ 
public class NuccExPayManager {
    
    
    @Resource(name = "nuccConfig")
    private Map<String, String> nuccConfig;
        
    @Resource(name = "bankContractInfoDAO")
    private BankContractInfoDAO bankContractInfoDAO;

    @Resource(name = "nuccUrlConfig")
    private Map<String, String> nuccUrlConfig;
    
    @Resource(name = "bankOrderManager")
    private BankOrderManager bankOrderManager;
    
    @Resource(name="nuccExPayServiceClient")
    private ExPayService nuccExPayServiceClient;
    
    @Resource(name = "bisExpaySmsSendLogDAO")
    private BisExpaySmsSendLogDAO bisExpaySmsSendLogDAO;
    
    @Resource(name="nuccExPaySerialServiceClient")
    private SerialApplyService nuccExPaySerialServiceClient;
    
    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;

    @Resource(name = "commonPgGeneralOrderTransDtlDAO")
    private PgGeneralOrderTransDtlDAO commonPgGeneralOrderTransDtlDAO;

    @Resource(name = "custCorpInfoDao")
    private CustCorpInfoDao custCorpInfoDao;
    
    @Resource(name = "cpsGeneralReceiptOrderQueryDAO")
    protected CpsGeneralReceiptOrderQueryDAO recvOrderDAO;
    
    @Resource(name = "nuccSerialManager")
	private NuccSerialManager nuccSerialManager;

    /**
     * 备付金账户
     */
    @Value("${GOPAY.INSTG.ACCT.ID}")
    private String instgAcctId;
    /**
     * 备付金账户所属机构标识
     */
    @Value("${GOPAY.RESFD.ACCT.ISSRID}")
    private String resfdAcctIssrid;
    
    @Value("${NUCC.SERIAL.CONTROL}")
    private String nuccSerialControl;

    
    /** 
     * 网联通知解约（验签操作）
     * @param base
     * @return
     * @throws GopayException 
     * @author w_jiqing 
     */
    public Object cancelVerify(ExPayBaseMessage base)throws GopayException{
        NuccExpayRescindRes message = (NuccExpayRescindRes) base;
        BankLogUtils.printExPayManagerCancelVerifySendLog(message);
        boolean flag = (boolean) nuccExPayServiceClient.verify(message);
        message.setSuccess(flag);
        BankLogUtils.printExPayManagerCancelVerifyReturnLog(message);
        return message;
    }
    
    /** 
     * 身份认证请求，调用网联发送验证码 
     * @param base
     * @return
     * @throws GopayException 
     * @author w_jiqing 
     */
    public Object sendSms(ExPayBaseMessage base) throws GopayException{
    	nuccSerialManager.generateFlowIdBySerial(base,false,nuccSerialControl);
        NuccExpayBaseMessage message =this.buildSendSms(base);
        BankLogUtils.printExPayManagerSendSmsSendLog(message);
        NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayServiceClient.sendSms(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerSendSmsReturnLog(res);
        return res;
    }
    
    /** 
     * 签约请求，调用网联校验验证码
     * @param base
     * @return
     * @throws GopayException 
     * @author w_jiqing 
     */
    public Object checkSms(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = this.buildCheckSms(base);
        BankLogUtils.printExPayManagerCheckSmsSendLog(message);
        NuccExpayCertRes res = (NuccExpayCertRes) nuccExPayServiceClient.checkSms(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerCheckSmsReturnLog(res);
        return res;        
    }
    
    public Object rescind(ExPayBaseMessage base,String contract) throws GopayException{
    	nuccSerialManager.generateFlowIdBySerial(base,false,nuccSerialControl);
        NuccExpayBaseMessage message = this.buildRescind(base,contract);
        BankLogUtils.printExPayUnBindCardSendLog(message);
        NuccExpayRescindRes res = (NuccExpayRescindRes) nuccExPayServiceClient.cancel(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayUnBindCardRetuenLog(res);
        return res;
        
    }
    
    /** 
     * 协议支付请求
     * @param base
     * @return
     * @throws GopayException 
     * @author w_jiqing 
     */
    public Object payment(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = this.buildPayment(base);
        message.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerPaymentSendLog(message);
        NuccExpaymentRes res = (NuccExpaymentRes) nuccExPayServiceClient.payment(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerPaymentReturnLog(res);
        return res;        
    }
    
    public Object refundVerify(ExPayBaseMessage base) throws GopayException{
        NuccExpayRefundEndRes message = (NuccExpayRefundEndRes) base;
        BankLogUtils.printExPayManagerRefundVerifySendLog(message);
        boolean flag = (boolean) nuccExPayServiceClient.verify(message);
        message.setSuccess(flag);
        BankLogUtils.printExPayManagerRefundVerifyReturnLog(message);
        return message;
                
    }
    public Object payVerify(ExPayBaseMessage base) throws GopayException{
        NuccExpaymentEndRes message = (NuccExpaymentEndRes) base;
        BankLogUtils.printExPayManagerVerifySendLog(message);
        boolean flag = (boolean) nuccExPayServiceClient.verify(message);
        message.setSuccess(flag);
        BankLogUtils.printExPayManagerVerifyReturnLog(message, true);
        return message;
    }
    
    public Object queryOrder(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = this.buildQueryOrder(base);
        message.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerQuerySendLog(message);
        NuccExpayQueryRes res = (NuccExpayQueryRes) nuccExPayServiceClient.queryOrder(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExPayManagerQueryReturnLog(res);
        return res;       
    }
    
    public Object refund(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = this.buildRefund(base);
        message.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExpayManagerRefundSendLog(message);
        NuccExpayRefundRes res = (NuccExpayRefundRes) nuccExPayServiceClient.refund(message);
        res.setOutStlmCd(BankConstants.BANK_LOGO_NUCCPAY);
        BankLogUtils.printExpayManagerRefundReturnLog(res);
        return res;
    }
    
    public NuccExpayBaseMessage buildRescind(ExPayBaseMessage base,String contract) throws GopayException{
        NuccExpayBaseMessage message = new NuccExpayBaseMessage();
        BeanUtils.copyProperties(base, message);
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpayRescindBodyReq body = new NuccExpayRescindBodyReq();
        try{
            header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //报文类型代码
            header.setMsgTp(nuccConfig.get("NUCC.EXPAY.RESCIND.MSGTP"));
            //发起方所属机构标示
            header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //报文方向  11-支付机构到平台
            header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
            //签名证书序列号
            header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
            //加密证书序列号
            header.setNcrptnSN(nuccConfig.get("NUCC.EXPAY.NCRPTNSN"));
            
            NuccExpayRescindBodySgninf sgninf = new NuccExpayRescindBodySgninf();
            sgninf.setSgnAcctIssrId(BankOfAffiliationConstants.getAffiliation(message.getBank()));
            String cardNo = message.getCardNo();
            sgninf.setSgnAcctShrtId(cardNo.substring(cardNo.length()-4, cardNo.length()));
            //签约协议号
            sgninf.setSgnNo(contract);
            if(BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)){
                sgninf.setSgnAcctTp("01");
            }else{
                sgninf.setSgnAcctTp("00");
            }
            NuccExpayRescindBodyInstginf instginf = new NuccExpayRescindBodyInstginf();
            instginf.setInstgId(nuccConfig.get("GOPAY.ISSRID"));
            NuccExpayRescindBodyRescindinf resc = new NuccExpayRescindBodyRescindinf();
            resc.setTrxId(message.getBankOrderId());
            resc.setTrxDtTm(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));            
            body.setInstgInf(instginf);
            body.setSgnInf(sgninf);
            body.setRescindInf(resc);
            message.setMsgHeader(header);
            message.setMsgBody(body);            
        }catch(Exception e){
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6054,e);
        }
        return message;
        
    }
 
    /** 
     * 构建退款请求报文
     * @param base
     * @return 
     * @author w_jiqing 
     */
    public NuccExpayBaseMessage buildRefund(ExPayBaseMessage base)throws GopayException{
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) base;
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpayRefundBodyReq body = new NuccExpayRefundBodyReq();
        try{
            header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //报文类型代码
            header.setMsgTp(nuccConfig.get("NUCC.EXPAY.REFUND.MSGTP"));
            //发起方所属机构标示
            header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //报文方向  11-支付机构到平台
            header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
            //签名证书序列号
            header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
            
            NuccExpayRefundBodyPyerinf pyerInf = new NuccExpayRefundBodyPyerinf();
            //退款方账户所属机构标示
            pyerInf.setPyerAcctIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //退款方账户(付款方的支付账户编号)
            CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getTkOriOrderId());
            pyerInf.setPyerAcctId(mainOrder.getMainRecvAcct());
            
            CpsGenReceiptOrder orgRecvOrder = recvOrderDAO.find(CpsGenReceiptOrder.class, message.getTkOriOrderId());
            message.setCardNo(orgRecvOrder.getEpBankCardNo()); 
            //退款方账户类型
            pyerInf.setPyerAcctTp("04");
            
            NuccExpayRefundBodyPyeeinf pyeeInf = new NuccExpayRefundBodyPyeeinf();
            BankOrder oriBankOrder = bankOrderManager.getBankOrderById(message.getTkOriBankOrderId());
            //收款方账户所属机构标示
            pyeeInf.setPyeeAcctIssrId(BankOfAffiliationConstants.getAffiliation(oriBankOrder.getBankCode()));
            if(BisBankBusinessProd._05.value.equals(oriBankOrder.getBankBizProdCode())){
                pyeeInf.setPyeeAcctTp("01");
            }else{
                pyeeInf.setPyeeAcctTp("00");
            } 
            BisBankContractInfo contractInfo = findContractInfo(orgRecvOrder.getEpBankCardNo(),oriBankOrder);
            if(contractInfo !=null){
                //协议号
                pyeeInf.setSgnNo(contractInfo.getContractNumber());
            }
            NuccExpayRefundBodyResfdinf resfdInf = new NuccExpayRefundBodyResfdinf();
            String[] aInfo = nuccSerialManager.getAccountInfo(oriBankOrder.getBankCode());            
            //支付机构备付金账户
            resfdInf.setInstgAcctId(aInfo[0]);
            //备付金账户所属机构标示
            resfdInf.setResfdAcctIssrId(aInfo[1]);
            
            NuccExpayRefundBodyTrxinf trxInf = new NuccExpayRefundBodyTrxinf();
            //交易类别
            trxInf.setTrxCtgy(nuccConfig.get("NUCC.EXPAY.REFUND.TRXCTGY"));
            //交易流水号
            trxInf.setTrxId(message.getBankOrderId());
            String bankOrderId = message.getBankOrderId();
            trxInf.setTrxId(bankOrderId);
            String ip =bankOrderId.substring(bankOrderId.length()-6, bankOrderId.length()-4) ;
            message.setPayUrl(this.getUrlBySerial(ip));
            //交易日期时间
            trxInf.setTrxDtTm(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //交易金额
            String amount = "CNY"+amountFormat(message.getAmount().toString());
            trxInf.setTrxAmt(amount);
            
            NuccExpayRefundBodyOriTrxinf oriTrxInf = new NuccExpayRefundBodyOriTrxinf();
            //原支付交易流水号
            oriTrxInf.setOriTrxId(message.getTkOriBankOrderId());
            //原付款银行流水号
            oriTrxInf.setOriDbtrBankId(oriBankOrder.getBankOrderId());
            oriTrxInf.setOriTrxAmt("CNY"+amountFormat(oriBankOrder.getSendBankAmt().toString()));
            
            body.setPyerInf(pyerInf);
            body.setPyeeInf(pyeeInf);
            body.setResfdInf(resfdInf);
            body.setTrxInf(trxInf);
            body.setOriTrxInf(oriTrxInf);
            message.setMsgHeader(header);
            message.setMsgBody(body);
        }catch(Exception e){
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6087,e);
        }       
        return message;
        
    }
    
    /** 
     * 构建订单查询请求报文
     * @param base
     * @return 
     * @author w_jiqing 
     */
    public NuccExpayBaseMessage buildQueryOrder(ExPayBaseMessage base){
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) base;
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpayQueryBodyReq body = new NuccExpayQueryBodyReq();
        
        CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
        BankOrder bankOrder =bankOrderManager.getBankOrderById(message.getBankOrderId());
        header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
        //报文类型代码
        header.setMsgTp(nuccConfig.get("NUCC.EXPAY.QUERY.MSGTP"));
        //发起方所属机构标示
        header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
        //报文方向  11-支付机构到平台
        header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
        //签名证书序列号
        header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
        
        NuccExpayQueryBodyOriTrxinf oriTrxInf = new NuccExpayQueryBodyOriTrxinf();
        
        if(BisBankBusinessProd._12.value.equals(bankOrder.getBankBizProdCode())){
            //退款交易类别
            oriTrxInf.setOriTrxCtgy(nuccConfig.get("NUCC.EXPAY.REFUND.TRXCTGY"));
        }else{
            //支付交易类别
            oriTrxInf.setOriTrxCtgy(nuccConfig.get("NUCC.EXPAY.PAY.TRXCTGY"));
        }       
        oriTrxInf.setOriTrxId(base.getBankOrderId());
        oriTrxInf.setOriTrxDtTm(DateUtils.format(mainOrder.getCreatedTs(), "yyyy-MM-dd HH:mm:ss").replace(" ", "T"));        
        body.setOriTrxInf(oriTrxInf);
        body.setInstgId(nuccConfig.get("GOPAY.ISSRID"));
        //设置支付地址
        String bankOrderId=base.getBankOrderId();
        String ip =bankOrderId.substring(bankOrderId.length()-6, bankOrderId.length()-4) ;
        message.setPayUrl(this.getUrlBySerial(ip));
        message.setMsgHeader(header);
        message.setMsgBody(body);
        return message;
        
    }
    
    /** 
     * 构建支付请求报文
     * @param base
     * @return 
     * @author w_jiqing 
     */
    public NuccExpayBaseMessage buildPayment(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) base;
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpaymentBodyReq body = new NuccExpaymentBodyReq();
        try{
            //通过订单号获取主订单信息
            CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
            //获取商户信息
            CustCorpInfo custCorpInfo = custCorpInfoDao.getByCustId(mainOrder.getMerId());
            //拼接订单详情
            StringBuilder orderDescSb = new StringBuilder();
            if (null != custCorpInfo) {
                orderDescSb.append("1|1|").append(custCorpInfo.getCorpName())
                        .append("%").append(mainOrder.getMerId()).append("%")
                        .append(custCorpInfo.getCorpType()).append("%")
                        .append("").append("%").append("").append("%")
                        .append(custCorpInfo.getGopayMccCode()).append("%");
            }else{
                orderDescSb.append("||").append("").append("%").append("").append("%")
                        .append("").append("%").append("").append("%").append("").append("%")
                        .append("").append("%");
            }
            //获取交易流水信息
            String hql = " from PgGenOrderTransDtl where transDtlSq = :transDtlSq";
            Map paramMap = new HashMap();
            paramMap.put("transDtlSq",mainOrder.getTransDtlSq());
            List<PgGenOrderTransDtl> transDtls = commonPgGeneralOrderTransDtlDAO.findByHql(hql, paramMap);
            if (null != transDtls && transDtls.size()>0) {
                PgGenOrderTransDtl transDtl = transDtls.get(0);
                orderDescSb.append("1#1#").append(transDtl.getGoodsName())
                        .append("^").append(transDtl.getMerTxnAmt())
                        .append("^").append("|");
            }else{
                orderDescSb.append("##").append("").append("^").append("").append("^").append("|");
            }
            header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //报文类型代码
            header.setMsgTp(nuccConfig.get("NUCC.EXPAY.PAY.MSGTP"));
            //发起方所属机构标示
            header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //报文方向  11-支付机构到平台
            header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
            //签名证书序列号
            header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
            
            NuccExpaymentBodyPyerinf pyerInf = new NuccExpaymentBodyPyerinf();
            //付款方账户所属机构标示
            pyerInf.setPyerAcctIssrId(BankOfAffiliationConstants.getAffiliation(message.getBank()));
            if(BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)){
                //账户类型
                pyerInf.setPyerAcctTp("01");
            }else{
                pyerInf.setPyerAcctTp("00");
            }
            //签约协议号
            pyerInf.setSgnNo(message.getAgrmtNo());
            
            NuccExpaymentBodyPyeeinf pyeeInf = new NuccExpaymentBodyPyeeinf();
            //收款方账户所属机构标示
            pyeeInf.setPyeeAcctIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //收款方账户
            pyeeInf.setPyeeAcctId(mainOrder.getMainRecvAcct());
            //收款方名称
            pyeeInf.setPyeeNm(custCorpInfo.getCorpName());
            //收款方账户类型
            pyeeInf.setPyeeAcctTp("04");
            
            NuccExpaymentBodyResfdinf resfdInf = new NuccExpaymentBodyResfdinf();
            String[] aInfo = nuccSerialManager.getAccountInfo(message.getBank());           
            //支付机构备付金账户
            resfdInf.setInstgAcctId(aInfo[0]);
            //备付金账户所属机构标示
            resfdInf.setResfdAcctIssrId(aInfo[1]);
            
            NuccExpaymentBodyTrxinf trxInf = new NuccExpaymentBodyTrxinf();
            trxInf.setTrxDtTm(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            // 金额，以分为单位
            String amount = "CNY"+amountFormat(message.getAmount().toString());
            trxInf.setTrxAmt(amount);
            //交易类别
            trxInf.setTrxCtgy(nuccConfig.get("NUCC.EXPAY.PAY.TRXCTGY"));
            trxInf.setTrxId(message.getBankOrderId());
            //业务种类
            trxInf.setBizTp("100007");
            
            NuccExpaymentBodyOrdrinf ordrInf = new NuccExpaymentBodyOrdrinf();
            //订单编码
            ordrInf.setOrdrId(message.getOrderId());
            //订单详情
            ordrInf.setOrdrDesc(orderDescSb.toString());
            
            body.setPyerInf(pyerInf);
            body.setPyeeInf(pyeeInf);
            body.setResfdInf(resfdInf);
            body.setTrxInf(trxInf);
            body.setOrdrInf(ordrInf);
            message.setMsgHeader(header);
            message.setMsgBody(body);  
            message.setCustomerID(null);
        }catch(Exception e){
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6057,e);
        }        
        return message;
        
    }

    
    /** 
     * 构建发短信（身份认证报文）
     * @param base
     * @return 
     * @author w_jiqing 
     */
    public NuccExpayBaseMessage buildSendSms(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) base;
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpayCertBodyReq body = new NuccExpayCertBodyReq();
        try{
            header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //报文类型代码
            header.setMsgTp(nuccConfig.get("NUCC.EXPAY.AUTH.MSGTP"));
            //发起方所属机构标示
            header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //报文方向  11-支付机构到平台
            header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
            //签名证书序列号
            header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
            //加密证书序列号
            header.setNcrptnSN(nuccConfig.get("NUCC.EXPAY.NCRPTNSN"));

            NuccExpayCertBodySgninf sgnInf = new NuccExpayCertBodySgninf();
            //签约人银行账户所属机构标示
            sgnInf.setSgnAcctIssrId(BankOfAffiliationConstants.getAffiliation(message.getBank()));
            if(BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)){
                //账户类型
                sgnInf.setSgnAcctTp("01");
            }else{
                sgnInf.setSgnAcctTp("00");
            }
            //账户编号
            sgnInf.setSgnAcctId(message.getCardNo());
            //账户名称
            sgnInf.setSgnAcctNm(message.getCardHolder());
            //证件类型
            sgnInf.setIdTp("01");
            //证件号
            sgnInf.setIdNo(message.getIdentityCode());
            //手机号
            sgnInf.setMobNo(message.getMediaId());
            
            NuccExpayCertBodyTrxinf trxInf = new NuccExpayCertBodyTrxinf();
            //交易类别
            trxInf.setTrxCtgy(nuccConfig.get("NUCC.EXPAY.AUTH.TRXCTGY"));
            trxInf.setTrxId(message.getBankOrderId());
            
            //交易日期时间
            trxInf.setTrxDtTm(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            
            NuccExpayCertBodyInstginf instgInf = new NuccExpayCertBodyInstginf();
            //支付账户所属机构标示
            instgInf.setInstgId(nuccConfig.get("GOPAY.ISSRID"));
            
            body.setInstginf(instgInf);
            body.setSgninf(sgnInf);
            body.setTrxinf(trxInf);        
            message.setMsgHeader(header);
            message.setMsgBody(body);
        }catch(Exception e){
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6077,e);
        }        
        return message;
    }

    /** 
     * 构建发送短信（签约报文）
     * @param base
     * @return 
     * @author w_jiqing 
     */
    public NuccExpayBaseMessage buildCheckSms(ExPayBaseMessage base) throws GopayException{
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) base;
        NuccExpayHeaderMessage header = new NuccExpayHeaderMessage();
        NuccExpayCertBodyReq body = new NuccExpayCertBodyReq();
        try{
            BisExpaySmsSendLog bessl= bisExpaySmsSendLogDAO.getBisExpaySmsSendLog(message.getOrderId(),SMSType.CASHIER_SMS_SEND.value);
            header.setSndDt(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            //报文类型代码
            header.setMsgTp(nuccConfig.get("NUCC.EXPAY.SIGN.MSGTP"));
            //发起方所属机构标示
            header.setIssrId(nuccConfig.get("GOPAY.ISSRID"));
            //报文方向  11-支付机构到平台
            header.setDrctn(nuccConfig.get("NUCC.EXPAY.DRCTN"));
            //签名证书序列号
            header.setSignSN(nuccConfig.get("NUCC.EXPAY.SIGNSN"));
            //加密证书序列号
            header.setNcrptnSN(nuccConfig.get("NUCC.EXPAY.NCRPTNSN"));
            
            NuccExpayCertBodySgninf sgnInf = new NuccExpayCertBodySgninf();
            //签约人银行账户所属机构标示
            sgnInf.setSgnAcctIssrId(BankOfAffiliationConstants.getAffiliation(message.getBank()));
            if(BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)){
                //账户类型
                sgnInf.setSgnAcctTp("01");
            }else{
                sgnInf.setSgnAcctTp("00");
            }
            //账户编号
            sgnInf.setSgnAcctId(message.getCardNo());
            //账户名称
            sgnInf.setSgnAcctNm(message.getCardHolder());
            //证件类型
            sgnInf.setIdTp("01");
            //证件号码
            sgnInf.setIdNo(message.getIdentityCode());
            //手机号
            sgnInf.setMobNo(message.getMediaId());
            
            NuccExpayCertBodyTrxinf trxInf = new NuccExpayCertBodyTrxinf();
            //交易类别
            trxInf.setTrxCtgy(nuccConfig.get("NUCC.EXPAY.SIGN.TRXCTGY"));
            if(bessl != null){
                //网联认证和签约时，需保持同一个流水号
                String bankOrderId = bessl.getRemark();
                trxInf.setTrxId(bankOrderId);
                String ip =bankOrderId.substring(bankOrderId.length()-6, bankOrderId.length()-4) ;
                message.setPayUrl(this.getUrlBySerial(ip));
            }
            //交易日期时间
            trxInf.setTrxDtTm(DateUtils.now2string("yyyy-MM-dd HH:mm:ss").replace(" ", "T"));
            trxInf.setAuthMsg(message.getValidateCode());
            
            NuccExpayCertBodyInstginf instgInf = new NuccExpayCertBodyInstginf();
            //支付账户所属机构标示
            instgInf.setInstgId(nuccConfig.get("GOPAY.ISSRID"));
            
            body.setInstginf(instgInf);
            body.setSgninf(sgnInf);
            body.setTrxinf(trxInf);        
            message.setMsgHeader(header);
            message.setMsgBody(body);
        }catch(Exception e){
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6078,e);
        }        
        return message;
        
    }

    
    /**
     * 通过流水号规则获取url
     * @param serial
     * @return
     */
    private String getUrlBySerial(String serial){
        //获取流水号规则前两位
        String idc = serial.substring(0,2);
        //从map中获取idc对应的url
        String url = nuccUrlConfig.get(idc);
        return url;
    }
    
    private String amountFormat(String amount){
        DecimalFormat df = new DecimalFormat("0.00");
        return  df.format(new BigDecimal(amount));
    }

    
    /**
     * 根据卡号和签约银行查询生效签约记录
     * 
     * @param cardNo
     * @param oriBankOrder
     * @return
     */
    public BisBankContractInfo findContractInfo(String cardNo,BankOrder oriBankOrder) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(oriBankOrder.getBankCode());
        bisBankContractInfo.setCardNo(cardNo);
        bisBankContractInfo.setBankBizProdCode(oriBankOrder.getBankBizProdCode());
        bisBankContractInfo.setIntrfaceChannelCode(oriBankOrder.getInterfaceChennelCode());
        return bankContractInfoDAO.getContractInfoByCard(bisBankContractInfo);
    }



    public Map<String, String> getNuccConfig() {
        return nuccConfig;
    }

    public void setNuccConfig(Map<String, String> nuccConfig) {
        this.nuccConfig = nuccConfig;
    }

    public Map<String, String> getNuccUrlConfig() {
        return nuccUrlConfig;
    }

    public void setNuccUrlConfig(Map<String, String> nuccUrlConfig) {
        this.nuccUrlConfig = nuccUrlConfig;
    }

    public BankOrderManager getBankOrderManager() {
        return bankOrderManager;
    }

    public void setBankOrderManager(BankOrderManager bankOrderManager) {
        this.bankOrderManager = bankOrderManager;
    }

    public ExPayService getNuccExPayServiceClient() {
        return nuccExPayServiceClient;
    }

    public void setNuccExPayServiceClient(ExPayService nuccExPayServiceClient) {
        this.nuccExPayServiceClient = nuccExPayServiceClient;
    }

    public SerialApplyService getNuccExPaySerialServiceClient() {
        return nuccExPaySerialServiceClient;
    }

    public void setNuccExPaySerialServiceClient(SerialApplyService nuccExPaySerialServiceClient) {
        this.nuccExPaySerialServiceClient = nuccExPaySerialServiceClient;
    }

    public CpsGeneralMainOrderQueryManager getMainOrderQuery() {
        return mainOrderQuery;
    }

    public void setMainOrderQuery(CpsGeneralMainOrderQueryManager mainOrderQuery) {
        this.mainOrderQuery = mainOrderQuery;
    }

    public PgGeneralOrderTransDtlDAO getCommonPgGeneralOrderTransDtlDAO() {
        return commonPgGeneralOrderTransDtlDAO;
    }

    public void setCommonPgGeneralOrderTransDtlDAO(PgGeneralOrderTransDtlDAO commonPgGeneralOrderTransDtlDAO) {
        this.commonPgGeneralOrderTransDtlDAO = commonPgGeneralOrderTransDtlDAO;
    }

    public CustCorpInfoDao getCustCorpInfoDao() {
        return custCorpInfoDao;
    }

    public void setCustCorpInfoDao(CustCorpInfoDao custCorpInfoDao) {
        this.custCorpInfoDao = custCorpInfoDao;
    }
}
